/**
 * ajax 请求
 * Created by Administrator on 2017-08-11.
 */
import DateUtil from '@/mpf/date-util'
import TokenManager from '@/mpf/token-manager'
import AjaxCache from '@/mpf/cache/ajaxcache'
import AuthEncrypt from '@/mpf/auth-encrypt'
import Md5 from '@/mpf/md5.js'

import CryptoJS from '@/mpf/crypto-js.js'

import JSEncrypt from '@/js_sdk/rsa/jsencrypt.min.js';

var METHOD_GET = 'GET'
var METHOD_POST = 'POST'
var METHOD_PUT = 'PUT'
var METHOD_DELETE = 'DELETE'

const encrypt = new JSEncrypt();

const PRIVATE_KEY =`-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD3PesCUDhiQEMc
7SQE+kvjnlD3KUu0MhCTZSysHxS4YEUaUr781J8TC+TzEZsiKAkK1kr6mqzvzrlJ
YqPKYF8tebZ29bX3KK8BhNI2tjHHRWmHdVMCCrP3+pfLn/wCmly81bhactl47S0I
ivxyWTKgcZIJZupxt4btoSDLCbOht/nXryFe/nwM/ou28dhzf75mmLVawEkoa1H8
ib9yp81f6szXWQAFQEmUCWrrL73nVSSOLmWsoStmNCPQ6KnY4+A83Ot9nN1WqgwH
zz/cY1Plme1fiZRlDOVsHwMKqJgl73ITVLwNRdzVxzN4xSV6XWt0k7N2TFxOzLQ/
PqCGSwUpAgMBAAECggEBAJJgBhKIi9kfUpx9iSWpSeSohibOPBOi0E1zSM9eV1YR
KNg8xPXKq6MLF7EQa1f9e9z+ocVcbaZMLUZVL8NQ6whxVqV3MxPw8itkB1B87Vuc
rK2VuF8tFv9pTRUw0nJ4EQ97OHnUJQyC3naAUpUgWejDVEJcu9A3Z5qoGlIanE7R
AyCUYDxOfhxuscVvxjL+FsPy3Br8XO3pMiD9KySSjmk83w92YnB/f7tXMzD283UG
qc8NcxKU8kkPavISSjeZOWFPoQzxsvLbHomMBAxrXeOoysNthxR6ONg6qolC1yZ5
2l2p724xHneySNSJPaaRdzyyPygQO2RjH6A3i4vPC0ECgYEA/jY2xJPVu+mlXZBu
GRiHVT6fovQlY/YmMPD5hZdUQpcDu872Wd8ZkMYKTFdh7gveITEY3Y3f8nHLLCxc
xHf1GPJ5wS/sWBQX0aulci2l7sy+kfGNx8rzl/BS+d2vbX1IzU/rLsUDqpw2LCBA
nNhgiyBtH6UQUpKN84CKf4Bnml8CgYEA+PsnEgwyZNspXsoiIHVwe0zbnkqS7PDH
L/fuu+dgS8n9SVL8PIlfF9laIL2KpGPlcaS3Whe8BIBGa6atEYvFLboEj8amtBoL
1PwiHOhiHfOMMTpOfpMfcXc8BjGitFy93OAZIQW/a7NiyXBBsgQrwzRP/K7S3tg6
7Q+gT3NKnXcCgYBJAjz8fBDYZSQPGRnlrzu+6btjS4cpjFovmCWxjmKutTxnRetO
qFppT9dJUZdYjKQBGF6x0rtMoA3f4+XIr0L/JTR+nUrdiPfGSeu8PQv452ib9ano
hYssSeMqy9ZENcUg4iEDT6Xb6/1K8wBbi3E+w9NTUU68yEZodrRQJgqbNQKBgQCu
O+Ndh9eEKLJMuRskp8ptHp3ZqcojsWNSuCgCqqoCn3l2ZHJLUr6PC/U8UCfDXnzk
CCafD1jttW6SSvN2Ad+cXj5u9s8V3dxF0aN1o1F2MEb89BaWERLB7nS8yONZYEUl
WlV7fHA2SDRrTvlKQAz375XB9/1tINgrqPHAZ6fhhQKBgQDVE/cstig/K0eiHyTJ
Fx2NnwunNlYPZYzuE5ezpKJvqFsjxQj8fRZIjKq5NigC0ZUla/u8iNBxbrzvF5OK
VM5FKClODhH1fwcfX4r4vM3x+dP3aJNJGmHF62vLHjpjPPPayvRSLG0hZZXTTcDp
KVoNP2QkaZPYR0XYUVhA7v8xsA==
-----END PRIVATE KEY-----`;

encrypt.setPrivateKey(PRIVATE_KEY);

var lockMap = {}

/**
 * 错误提示
 * @type {Function}
 */
function showError(message){
  (global.toast || global.showError || global.alert)(message)
}

/**
 * 是否为数组
 */
function isArray (v) {
  return toString.apply(v) === '[object Array]'
}

/**
 * 编码请求参数
 * @param val
 * @param pctEncodeSpaces
 * @returns {string}
 */
function encodeUriQuery(val, pctEncodeSpaces) {
  return encodeURIComponent(val)
    .replace(/%40/gi, '@')
    .replace(/%3A/gi, ':')
    .replace(/%24/g, '$')
    .replace(/%2C/gi, ',')
    .replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'))
    .replace(/'/g, '%27')
}

/**
 * 请求数据格式化
 * @param {Object} urlOld
 * @param {Object} paramData
 * @param {Object} method
 */
function httpUrlFormat(urlOld, paramData, method) {
  if (paramData) {
    var urlArray = []

    paramData = isArray(paramData) ? (paramData.length > 0 ? paramData[0] : []) : paramData
    for (var key in paramData) {
      var value = paramData[key]
      if (isArray(value)) {
        if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') {
          var arrayValueCell = []
          for (var keyCell in value) {
            var valueCell = value[keyCell]
            arrayValueCell.push(key + '=' + encodeUriQuery(valueCell))
          }
          if (arrayValueCell.length > 0) {
            urlArray.push(arrayValueCell.join('&'))
          }
        }
      } else {
        if (urlOld.indexOf(':' + key, value) !== -1) {
          urlOld = urlOld.replace(':' + key, encodeUriQuery(value))
        } else {
          if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') {
            urlArray.push(key + '=' + encodeUriQuery(value))
          }
        }
      }
    }

    urlArray.sort(function (a, b) {
      return a.localeCompare(b)
    })
    urlOld = encodeURI(urlOld) + (urlArray.length > 0 ? ('?' + urlArray.join('&')) : '')
  } else {
    urlOld = encodeURI(urlOld)
  }
  return (urlOld)
}

/**
 * 授权头
 * @param {Object} method
 * @param {Object} url
 * @param {Object} token
 */
function generateAuthorization(method, url, token){
	return AuthEncrypt.getMac(method, url, token);
}

/**
 * 参数重组
 * @param args
 */
function rebuild(args){
  var config = {};
  if(args.length === 1){
    if (typeof args[0] === 'string') {
      config.url = args[0]
    }
    else{
      config = args[0]
    }
  } else if (args.length === 2) {
    config = args[1] ? args[1] : {}
    config.url = args[0]
  }
  else if(args.length === 3) {
    config = args[2] ? args[2] : {}
    config.url = args[0]
    if(args[1] !== null){
      config.data = args[1]
    }
  }
  return config
}

var Http = {
  get: function () {
    var config = rebuild(arguments)
    config.method = METHOD_GET
    return Http.execute(config)
  },
  post: function () {
    var config = rebuild(arguments)
    config.method = METHOD_POST
    return Http.execute(config)
  },
  put: function () {
    var config = rebuild(arguments)
    config.method = METHOD_PUT
    return Http.execute(config)
  },
  delete: function () {
    var config = rebuild(arguments)
    config.method = METHOD_DELETE
    return Http.execute(config)
  },
  upload: function(){
    var config = rebuild(arguments)
    config.method = METHOD_POST
    return Http.doUpload(config)  

  },
  /**
   * 下载
   */
  download: function(){
	  var config = rebuild(arguments)
	  config.method = METHOD_GET
	  return Http.execDownload(config)  
  },
  execute: function (config) {
    // 使用Promise 处理成功
    if (config.success == null) {
      return new Promise(function (resolve, reject) {
        config.success = function (res) {
          resolve(res)
        }
		if(config.customReject){
			config.reject = function(err) {
				reject(err)
			}
		}
		else{
			config.commonReject = function(err){
				console.log(err);
				reject(err)
			}
		}
		
        Http.doExecute(config)
      })
    } else {
      return Http.doExecute(config)
    }
  },
  /**
   * Aes请求
   * @param {Object} action
   * @param {Object} data
   */
  aesRequest: function(action, data){
	let text = JSON.stringify({action: action, data: data});
	let key = CryptoJS.enc.Utf8.parse(global.APP_SECRET_KEY);
	let iv = CryptoJS.enc.Utf8.parse(global.APP_AES_IV);
	let config = {
		form:{
			content: CryptoJS.AES.encrypt(text, key, {
				iv: iv,
				mode: CryptoJS.mode.CBC,
				padding: CryptoJS.pad.Pkcs7,
			}).toString()
		}
	}
		
	return Http.post('/api/app/request', config);
	 
  },
  doExecute: function (config) {
	
    config.method = (config.method || config.type || METHOD_GET).toUpperCase()

    // 设置头部
    config.header = config.header || config.headers || {}
    // 普通表单方式提交
    if(config.form && config.method === METHOD_POST){
      config.header['Content-Type'] = config.header['Content-Type'] || 'application/x-www-form-urlencoded'
    }
    else{
      config.header['Content-Type'] = config.header['Content-Type'] || 'application/json'
    }
    /**
     * 设置平台信息
     */
    config.header['platform'] = 'mini_program';
    
    config.header['x-app'] = global.APP_ID;
	
	var timestamp = Math.floor(new Date().getTime() / 1000);
	
	config.header['x-timestamp'] = timestamp;
	
	config.header['x-sign'] = Md5(timestamp, global.APP_SECRET_KEY);

    Http.combine(config)
	
	var lockKey = config.method + '#' + config.url + '#' + JSON.stringify(config.data||{});
	//非GET 对请求加锁处理
	if(config.method != METHOD_GET){
	  if(lockMap[lockKey]){
		console.log("重复请求：" + lockKey, lockMap);
		return ;
	  }
	  lockMap[lockKey] = true
	}

	
	// 配置 DEBUG userId 方便调试
    if(global.DEBUG_USERID){
        config.header['Authorization'] = "DEBUG userId=" + global.DEBUG_USERID;
    }
    else{
       // 设置授权头部
       var token = TokenManager.get();
       config.header['Authorization'] = generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
    }

   
    // 成功回调
    var successCallback = config.success || function (response, status, header, config) {}

    // 失败回调
    var errorCallback = config.fail || config.error || function (response, status, header) {
      if (config.ignore) {
        return
      }
      if (response && response.message) {
        showError(response.message)
      }
    }

    //请求完成回调
    var completeCallback = config.complete || function (res) {
      if(config.loading !== false){
        global.hideLoading();
      }
    }

	
    // 使用缓存数据
    if (config.method === METHOD_GET) {
			
		var lastResponse = AjaxCache.get(config.url)
		if (config.useLast && lastResponse) {
			successCallback(lastResponse)
		}
    }

    config.success = function (response) {
		let statusCode = response.statusCode;
		let data = response.data;
		if(data && data.code){
			if(typeof data.code == 'number'){
				statusCode = data.code;
			}
		}
		if(data && data['x-data']){
			let xData = data['x-data'];
			let xSign = data['x-signature'];
			data = encrypt.decryptLong(xData);
			data = JSON.parse(decodeURIComponent(data));
			let xTimestamp = data['x-timestamp'];
			delete data['x-timestamp'];
		}	
			
        if (statusCode == 200) {
		
			successCallback(data);
			//设置缓存数据
			if (config.useLast) {
				AjaxCache.set(config.url, response);
			}
		}
		else {
			if (statusCode == 401){
				TokenManager.clear();
			}
			if ((statusCode == 401) && !config.anonymous) {
				config.reject && config.reject(data);
				config.commonReject && config.commonReject(data)
				global.login();
			}
			else {
				if(data && !data.message){
					data.message = data.msg || '请求失败';
				}
				
				// 自定义reject处理
				if(config.reject){
					config.reject(data);
					return ;
				}
				
				
				if (data && data.message){
					errorCallback(data, statusCode, response.header)
					config.commonReject && config.commonReject(data)
				}
				else if(!config.anonymous){
					showError('请求失败');
							
				}
			}

		}
    }
	
    config.fail = config.fail || function (err) {
		showError('请求失败，请检查网络')
		
		config.reject && config.reject(err);
		config.commonReject && config.commonReject(err)
    }

    config.complete = function(res){
		delete lockMap[lockKey]
		completeCallback(res);
    }

    if (config.url.indexOf('http') !== 0) {
      config.url = config.baseURL + config.url;
    }
   
    
    // if (config.loading !== false) {
    //   var text = config.loadingText|| '';
    //   global.showLoading(text);
    // }
    uni.request(config);
  },
  /**
   * 执行上传
   */
  doUpload: function(config) {
    // 设置头部
    config.header = config.header || config.headers || {}
    /**
     * 设置平台信息
     */
   
    config.header['platform'] = 'mini_program';
    
    
    config.header['x-app'] = global.APP_ID;

    Http.combine(config)

    // 配置 DEBUG userId 方便调试
    if(global.DEBUG_USERID){
        config.header['Authorization'] = "DEBUG userId=" + global.DEBUG_USERID;
    }
    else{
       // 设置授权头部
       var token = TokenManager.get();
       config.header['Authorization'] = generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
    }
	
    // 成功回调
    var successCallback = config.success || function (response, status, header, config) { }

    // 失败回调
    var errorCallback = config.fail || config.error || function (response, status, header) {
      if (config.ignore) {
        return
      }
      if (response && response.message) {
        showError(response.message)
      }
    }

    //请求完成回调
    var completeCallback = config.complete || function (res) {
      if (config.loading !== false) {
        global.hideLoading();
      }
    }

    config.success = function (response) {
      if (response.statusCode == 200) {
        successCallback(JSON.parse(response.data));
      }
      else {
		if (response.statusCode == 401){
		  	//TokenManager.clear();
		}
        if ((response.statusCode == 401) && !config.anonymous) {
          global.login();
        }
        else {
          if (response && response.data && response.data.message) {
            errorCallback(response.data, response.statusCode, response.header)
          }
          else if(!config.anonymous){
				showError('请求失败');
				
          }
        }
      }
    }

    config.fail = config.fail || function (res) {
      showError('请求失败，请检查网络或参数')
    }

    config.complete = function (res) {
      completeCallback(res);
    }
    config.formData = config.formData || config.data;
    delete config.data;

    if (config.url.indexOf('http') !== 0) {
      config.url = config.baseURL + config.url;
    }

    return uni.uploadFile(config);
  },
  
  /**
   * 执行下载
   */
  execDownload: function(config) {
    // 设置头部
    config.header = config.header || config.headers || {}
    /**
     * 设置平台信息
     */
    config.header['platform'] = 'mini_program';
    
    config.header['x-app'] = global.APP_ID;
  
    Http.combine(config)
	
    // 设置授权头部
	Http.setAuthorization(config);
  
    // 成功回调
    var successCallback = config.success || function (response, status, header, config) { }
  
    // 失败回调
    var errorCallback = config.fail || config.error || function (response, status, header) {
      if (config.ignore) {
        return
      }
      if (response && response.message) {
        showError(response.message)
      }
    }
  
    //请求完成回调
    var completeCallback = config.complete || function (res) {
      if (config.loading !== false) {
        global.hideLoading();
      }
    }
  
    config.success = function (response) {
      if (response.statusCode == 200) {
        successCallback(response);
      }
      else {
  		if (response.statusCode == 401){
  		  	//TokenManager.clear();
  		}
        if ((response.statusCode == 401) && !config.anonymous) {
          global.login();
        }
        else {
           if (response && response.data && response.data.message) {
              errorCallback(response.data, response.statusCode, response.header)
			}
            else if(!config.anonymous){
  				showError('请求失败');
  				
            }
        }
      }
    }
  
    config.fail = config.fail || function (res) {
      showError('请求失败，请检查网络或参数')
    }
  
    config.complete = function (res) {
      completeCallback(res);
    }
    config.formData = config.formData || config.data;
    delete config.data;
  
    if (config.url.indexOf('http') !== 0) {
      config.url = config.baseURL + config.url;
    }
  
    return uni.downloadFile(config);
  },
  /**
   * 设置Authorization
   * @param {Object} config
   */
  setAuthorization:function(config){
	// 配置 DEBUG userId 方便调试
	if(global.DEBUG_USERID){
	    config.header['Authorization'] = "DEBUG userId=" + global.DEBUG_USERID;
	}
	else{
	   // 设置授权头部
	   var token = TokenManager.get();
	   config.header['Authorization'] = generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
	}  
  },
  /**
   * 获取授权信息
   * @param config
   */
  getAuthorization: function (config) {
    config.method = (config.method || config.type || METHOD_GET).toUpperCase()
    Http.combine(config)
	
	// 配置 DEBUG userId 方便调试
	if(global.DEBUG_USERID){
	    return "DEBUG userId=" + global.DEBUG_USERID;
	}
	else{
	   // 设置授权头部
	   var token = TokenManager.get();
	   return token;
	}
  },
  /**
   * 数据合并
   * @param config
   */
  combine: function (config) {
    // 替换路径占位符号
    if (config.path) {
		for (var key in config.path) {
			config.url = config.url.replace('{' + key + '}', config.path[key])
		}
		delete config.path
    }
    config.data = config.data || config.body || config.form;


    var isFormData = config.isFormData
    if (!isFormData) {
      // 过滤掉null数据
      var data = config.data;
      var method = config.method
      if(config.query){
        data = config.query
        method = METHOD_GET
      }
      config.data = Http.filter(config.data)
      data = Http.filter(data)
      config.url = httpUrlFormat(config.url, data, method)
    }
    // 非http开头的加上API_BASE_PATH
    if (config.url.indexOf('http') !== 0) {
      if (!global.API_BASE_PATH) {
		uni.reLaunch({
			url:'/pages/welcome/welcome',
			fail: (error)=> {
				console.log(error);
			}
		})
		throw new Error('请配置接口基本地址global.API_BASE_PATH')
      }
      config.baseURL = global.API_BASE_PATH
    }
    delete config.body
    delete config.query
    delete config.form
  },
  filter: function (data) {
    if (Object.prototype.toString.call(data) === '[object Array]') {
      for(let i=0 ; i<data.length; i++){
        data[i] = Http.filter(data[i]);
      }
      return data;
    }
    
    var _data = {}
    for (var i in data) {
      var val = data[i]
      if (val === null || typeof val === 'undefined') {
        continue
      }
      if (/\d{4}-\d{1,2}-\d{1,2} {1}\d{1,2}:\d{1,2}:\d{1,2}$/.test(val)) {
        val = DateUtil.toDate(val)
      }
      _data[i] = val
    }
    return _data
  },
  /**
   * 组装请求头
   * @param {Object} config
   */
  combineHeaders(config){
	  
	  // 设置头部
	  config.header = config.header || config.headers || {}
	  
	  config.baseURL = global.API_BASE_PATH
	  
	  /**
	   * 设置平台信息
	   */

	  config.header['app-version'] = global.APP_VERSION;
	  config.header['platform'] = 'mini_program';
	  
	  config.header['x-app'] = global.APP_ID;
	  
	  // 参数组装
	  Http.combine(config)
	  
	  // 配置 DEBUG userId 方便调试
	  if(global.DEBUG_USERID){
	      config.header['Authorization'] = "DEBUG userId=" + global.DEBUG_USERID;
	  }
	  else{
	     // 设置授权头部
	     var token = TokenManager.get();
		 
		 config.header['Authorization'] = generateAuthorization(config.method, config.baseURL + decodeURIComponent(config.url), token)
	  }
  },
  /**
   * 生成请求头
   * @param {Object} url
   * @param {Object} method
   */
  generateHeaders(url, method){
	  let headers = {};
	  /**
	   * 设置平台信息
	   */
	  headers['platform'] = 'mini_program';
	  
	  headers['x-app'] = global.APP_ID;
	  
	  var timestamp = Math.floor(new Date().getTime() / 1000);
	  
	  headers['x-timestamp'] = timestamp;
	  
	  headers['x-sign'] = Md5(timestamp, global.APP_SECRET_KEY);
	  // 设置授权头部
	  var token = TokenManager.get();
	  headers['Authorization'] = generateAuthorization(method, url, token);
	  
	  return headers;
  }
  
}
export default Http

